#include "comunicaciones.h"

/* **************************************************************************
 * Función int iniciar_comunicacion()										*
 * Precondición: vacía														*
 * Postcondicion: 	-Devuelve un entero, que no es más que el identificador	*
 * 					de un socket por el que enviaremos los datos.			*
 * 					-En caso de error interno, terminará el programa		*
 * 					indicando en la salida de error la función que lanzó	*
 * 					el error												*
 ****************************************************************************/


int iniciar_comunicacion(){

	struct sockaddr_in direccion, direccion_remota;
	int sock, sock_acc;
	socklen_t sin_size= sizeof (struct sockaddr_in);

	direccion.sin_family = AF_INET;					//rellenamos la estructura
	direccion.sin_port = htons(PUERTO);				//de la dirección remota

	direccion.sin_addr.s_addr= INADDR_ANY;			//<--así se especifica que aceptará
													//conexión de cualquier IP
	memset(&(direccion.sin_zero), '\0', 8);

	sock= socket(AF_INET,SOCK_STREAM,0);

	if (sock==-1){
		fprintf(stderr,"Error en la funcion socket\n");
		exit(-1);
	}						//para ver lo que hacen estas funciones: man socket, man bind, man listen.

	if(bind(sock,(struct sockaddr *)&direccion, sizeof (direccion)) == -1){
		fprintf(stderr,"Error en la funcion bind\n");
		exit(-1);
	}

	if(listen(sock, 1)==-1){
		fprintf(stderr,"Error en la funcion bind\n");
		exit(-1);
	}

	//esperamos a que alguien se conecte en la función accept()
	//la funcion accept devuelve el nuevo socket para la comunicación
	//y no el que ya teníamos, lo cual nos permitiría ir abriendo varias comunicaciones
	//metiendo el accept en un while.
	fprintf(stdout,"Esperando conexión entrante...\n");

	sock_acc=accept(sock, (struct sockaddr *)&direccion_remota, &sin_size);

	if (sock_acc== -1){
		fprintf(stderr,"Error en la funcion accept\n");
		exit(-1);
	}

	fprintf(stdout,"conexión recibida\n");
	close(sock);
	return sock_acc;
}

/************************************************************************************
 * Función enviar_jugada(int sock, unsigned int columna)							*
 * Precondición: 																	*
 * 	-sock es un identificador válido de socket ya inicializado y listo				*
 * 	 para escribir/enviar sobre él.													*
 * 	-columna es un entero sin signo.												*
 * 																					*
 * Postcondición:																	*
 * 	-Envia por el socket con identificador sock un número entero positivo.			*
 * 	-Si hay un error en la comunicación, se imprimirá por la salida de error y		*
 * 	 se terminará el programa.														*
 ************************************************************************************/


void enviar_jugada(int sock,unsigned int columna){

	int bytes_enviados=0;

	bytes_enviados= send( sock, &columna, sizeof(unsigned int), 0);

	if (bytes_enviados== sizeof(unsigned int)){
		fprintf(stdout,"Jugada enviada.\n");
	}else{
		fprintf(stderr,"El envío fue erroneo o bien no completo.");
		exit(-1);
	}
}

/************************************************************************************
 * Función recibir_jugada(int sock, unsigned int columna)							*
 * Precondición: 																	*
 * 	-sock es un identificador válido de socket ya inicializado y listo				*
 * 	 para leer/recibir sobre él.													*
 * 																					*
 * Postcondición:																	*
 * 	-Se leee/recibe del socket un entero sin signo y se devuelve.					*
 * 	-Si hay un error en la comunicación, se imprimirá por la salida de error y		*
 * 	 se terminará el programa.														*
 ************************************************************************************/

unsigned int recibir_jugada(int sock){

	unsigned int columna_recibida;
	int bytes_recibidos;

	bytes_recibidos=recv(sock, &columna_recibida, sizeof (unsigned int), 0);

	if (bytes_recibidos== sizeof(unsigned int)){
		fprintf(stdout,"Jugada recibida.\n");
	}else{
		fprintf(stderr,"Hubo un problema en la recepción o bien la jugada no se recibió completamente.");
		exit(-1);
	}

	return columna_recibida;
};

/************************************************************************************
 * Función int conectar_con_servidor();												*
 * Precondición: 																	*
 * 	-La función leerá una dirección ip desde la entrada estándar ej: 172.22.11.222	*
 * 	-Existe un socket esperando la comunicación (accept).							*
 * 																					*
 * Postcondición:																	*
 * 	-Se crea un socket hacia la dirección del del servidor que se especifique.		*
 * 	-Si el servidor está esperando la comunicación se conectará a él y devolverá	*
 * 	 el identificador de socket.													*
 * 	-Si no, imprimirá error en la salida de error y saldrá del programa 			*
 ************************************************************************************/

int conectar_con_servidor(){

	char *ip=(char*)malloc(16*sizeof(char));		//crea un puntero a char y reserva un espacio para 12 caracteres
	int sock;
	struct sockaddr_in direccion_servidor;			//declaración de la estructura de dirección del servidor

	sock=socket(AF_INET,SOCK_STREAM,0);				//crea el socket

	fprintf(stdout, "Escriba la dirección IP del servidor: ");
	scanf("%s", ip);

	direccion_servidor.sin_family= AF_INET;					//rellenamos la estructura
	direccion_servidor.sin_port=htons(PUERTO);				//de la direccion de servidor
	direccion_servidor.sin_addr.s_addr= inet_addr(ip);		//<--Aquí introducimos la ip.
	memset(&(direccion_servidor.sin_zero), '\0', 8 );

	//ejecutamos el connect para vincular nuestro socket
	//con el del ordenador remoto esperando en la funcion accept()

	if (connect(sock, (struct sockaddr *)&direccion_servidor, sizeof(struct sockaddr))){
		fprintf(stderr,"Error en la función connect");
		exit(-1);
	}

	free(ip);		//liberamos la memoria reservada en la primera linea

	return sock;
};
